require 'SyntaxObjs'

class Pat
  @@all_pats = []
  
  attr_reader :lazy_copy, :parent
  attr_writer :lazy_copy
  
  def initialize(params={})
    @@all_pats << self
    @lazy_copy = false
    @parent = params[:parent]
    @name = params[:name]
    @sym_table = Hash.new()
  end
  
  def [] (key)
    key = key.kind_of?(SyntaxObject) ? key.syn_name : key
    if !@sym_table[key.to_s].nil?
      @sym_table[key.to_s]
    elsif !@parent.nil?
      @parent[key]
    else
      nil
    end
  end
  
  def []= (key,value)
    key = key.kind_of?(SyntaxObject) ? key.syn_name : key
    # puts "#{@name} => #{key}"
    @sym_table[key.to_s] = value
  end
  
  def lazy_clone
    ret = self.clone
    ret.lazy_copy = true
    return ret
  end
  
  def method_missing(symbol, *args, &block)
    @sym_table.send(symbol, *args, &block)
  end
  
  def delete(key)
    key = key.kind_of?(SyntaxObject) ? key.syn_name : key
    @sym_table.delete(key.to_s)
  end
  
  def to_s
    str = "Symbol Table for #{@name}\n=========================\n"
    @sym_table.each_pair {|k,v| str << "#{k} => #{v}\n"}
    str
  end
  
  def get_definations
    @sym_table.select do |key, value|
      value.syn_type == :def
    end
  end
  
  def self.all_pats
    @@all_pats
  end
end

class SymTableRecord
  attr_reader :syn_type, :object
  
  def initialize(type, object)
    @syn_type, @object = type, object
  end
  
  def to_s
    "#{@syn_type} : #{@object}"
  end
  
  def syn_type=(type)
    if @syn_type.nil? || @syn_type == :undef
      @syn_type = type
    end
  end
end
